package server;

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.StringTokenizer;

import common.Buffer;
import common.Sender;

public class ShellListener extends Thread{

	private Sender sender;
	private Buffer input;
	private ArrayList<Journal> journals;
	private ArrayList<Patient> patients;
	private SecurityKernel sk;
	private User user;
	private Auditor auditor;
	private Storage s;
	
	public ShellListener(Sender sender, Buffer input, ArrayList<Journal> j, ArrayList<Patient> p, User currentuser, Auditor auditor, Storage s){
		this.sender = sender;
		this.input = input;
		this.sk = new SecurityKernel();
		patients = p;
		user = currentuser;
		journals = j;
		this.auditor = auditor;
		this.s = s;
	}
	
	public void run(){
		while(true){
			String inline = input.poll();
			String in = arg(inline, 0);
			
			if (in.equals("help")){
				sender.send("help - this command\nls - list available journals\ncat <journal> - read specified journal\nrm <journal> - remove specified journal\ntouch <title> <patient> <division> <nurse> - create a journal and associate with a nurse\nedit <journal> <text> - replace current text in journal with text");
			}
			else if (in.equals("ls")){
				sender.send(list());
			}else if (in.equals("cat")){
				sender.send(read(arg(inline, 1)));
			}else if (in.equals("rm")){
				sender.send(remove(arg(inline, 1)));
			}else if (in.equals("touch")){
				sender.send(create(inline));
			}else if (in.equals("edit")){
				sender.send(edit(inline));
			}else{
				sender.send("unrecognized command (try 'help')");
			}
		}
	}
	
	private String edit(String inline) {
		String file = arg(inline, 1);
		int spaces = 0;
		int index = 0;
		try{
		for (int i = 0; i<3000; i++){
			if (inline.charAt(i) == ' '){
				spaces++;
			}
			if (spaces == 2){
				index = i; break;
			}
		}
		}catch(Exception e){
			return "syntax error";
		}
		String text = inline.substring(index + 1);
		
		Journal j = null;
		for (Journal journal : journals){
			if(journal.title().equals(file)){
				j = journal;
				break;
			}
		}
		
		if (!sk.mayEdit(user, j)){
			auditor.edit(user, j, false);
			return "access denied (user '" + user.getName() + "' has no edit permission for object '" + file + "')";
		}
		
		auditor.edit(user, j, true);
		j.setText(text);
		save();
		
		return "done";
	}

	private String create(String inline) {
		String title = arg(inline, 1);
		String patient = arg(inline, 2);
		String division = arg(inline, 3);
		String nurse = arg(inline, 4);
		Patient p = null;
		for (Patient pa : patients){
			if (pa.toString().equals(patient)){
				p = pa;
			}
		}
		
		if (!sk.mayCreate(user, p)){
			auditor.create(user, patient, false);
			return "access denied (user '" + user.getName() + "' has no create permission for patient '" + patient + "')";
		}
		
		auditor.create(user, patient, true);
		Journal newjournal = new Journal(title, p, division, nurse);
		save();
		return "done";
	}

	private String remove(String arg) {
		for (Journal journal : journals){
			if(journal.title().equals(arg)){
				if (!sk.mayRemove(user, journal)){
					auditor.remove(user, journal, false);
					return "access denied (user '" + user.getName() + "' has no remove permission for object '" + arg + "')";
				}
				auditor.remove(user, journal, true);
				journals.remove(journal);
				save();
				return "done";
			}
		}
		return "'" + arg + "': no such file";
	}

	private String read(String arg) {
		for (Journal journal : journals){
			if(journal.title().equals(arg)){
				if (!sk.mayRead(user, journal)){
					auditor.read(user, journal, false);
					return "access denied (user '" + user.getName() + "' has no read permission for object '" + arg + "')";
				}
				auditor.read(user, journal, true);
				return journal.toString();
			}
		}
		return "'" + arg + "': no such file";
	}

	private String list() {
		String s = "";
		for (Journal j : journals){
			s += j.title() + "\t" + j.getPatientName() + "\n";
		}
		return s.length() < 1 ? "" : s.substring(0, s.length() - 1);
	}

	private String arg(String text, int n){
		StringTokenizer toke = new StringTokenizer(text);
		String in = "";
		for (int i = -1; i<n; i++){
			in = toke.hasMoreTokens() ? toke.nextToken() : "";
		}
		return in;
	}
	
	private void save(){
		s.journals = journals;
		try{
			// Write to disk with FileOutputStream
			FileOutputStream f_out = new 
				FileOutputStream("storage");
	
			// Write object with ObjectOutputStream
			ObjectOutputStream obj_out = new
				ObjectOutputStream (f_out);
	
			// Write object out to disk
			obj_out.writeObject (s);
		}catch(Exception e){
			e.printStackTrace();
		}
	}
}
